home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / PacMan / Maze.m < prev    next >
Encoding:
Text File  |  1992-06-27  |  6.9 KB  |  282 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import <stdio.h>
  5. #import <libc.h>
  6. #import "Maze.h"
  7. #import "GameBrain.h"
  8. #import <appkit/NXImage.h>
  9. #import <appkit/Application.h>
  10. #import <appkit/defaults.h>
  11. #import <appkit/graphics.h>
  12.  
  13. @implementation Maze
  14.  
  15. - init
  16. {
  17.     char *appPath, *slashPos;
  18.     int i, j, k;
  19.     FILE *fp;
  20.     
  21.     [super init];
  22.     
  23.     // load image
  24.     mazeParts = [NXImage findImageNamed:"Maze.tiff"];
  25.     
  26.     
  27.     // get the path to the app wrapper (to find the maze file)
  28.     appPath = (char *)malloc(1024);
  29.     strcpy(appPath, NXArgv[0]);
  30.     if (slashPos = strrchr(appPath, '/')) {
  31.         sprintf(slashPos+1, "\0");
  32.     } else {
  33.         strcpy(appPath, "./");
  34.     }
  35.     strcat(appPath, "mazes");
  36.     
  37.     // read in the maze data
  38.     fp = fopen(appPath, "r");
  39.     if (fp == NULL) fprintf(stderr, "PacMan:  Cannot read maze data!\n");
  40.     for (i=0; i<MAZES; i++) {
  41.         for (j=BLOCK_HEIGHT-1; j>=0; j--) {
  42.             for (k=0; k<BLOCK_WIDTH; k++) {
  43.                 mazes[i][k][j] = getc(fp);
  44.                 switch(mazes[i][k][j]) { // handle special cases
  45.                     case 'D' : { mazes[i][k][j] = 5; // Door
  46.                                 break; }
  47.                     case '>' : { mazes[i][k][j] = 26; // door cap
  48.                                 break; }
  49.                     case '<' : { mazes[i][k][j] = 27; // door cap
  50.                                 break; }
  51.                     case ']' : { mazes[i][k][j] = 33; // end cap
  52.                                 break; }
  53.                     case '[' : { mazes[i][k][j] = 32; // end cap
  54.                                 break; }
  55.                     case ' ' : { mazes[i][k][j] = 28; // dot
  56.                                 break; }
  57.                     case 'O' : { mazes[i][k][j] = 29; // power dot
  58.                                 break; }
  59.                     case '|' : { mazes[i][k][j] = 31; // vert wall
  60.                                 break; }
  61.                     case '-' : { mazes[i][k][j] = 30; // horiz wall
  62.                                 break; }
  63.                     case '^' : { mazes[i][k][j] = 34; // end cap
  64.                                 break; }
  65.                     case 'P' : { mazes[i][k][j] = 7; // player (blank image)
  66.                                 break; }
  67.                     case 'G' : { mazes[i][k][j] = 10; // ghost (blank image)
  68.                                 break; }
  69.                     case '+' : { mazes[i][k][j] = 8; // blank (inside cage)
  70.                                 break; }
  71.                     default  : { mazes[i][k][j] -= 'a'; // get index
  72.                                 break; }
  73.                 }
  74.             }
  75.             getc(fp);
  76.         }
  77.     }
  78.     fclose(fp);
  79.     
  80.     // initizlize other instance vars.
  81.     [self makeMaze:1];
  82.     powerDotShown = YES;
  83.     visibleMaze = YES;
  84.     
  85.     return self;
  86. }
  87.  
  88.  
  89. - render:(NXRect *)rect at:(NXPoint *)pos     // used to render in another view
  90. {
  91.     int j, k;
  92.     NXRect from, check;
  93.     NXPoint pos2;
  94.     
  95.     if (!visibleMaze) return self;
  96.     for (j=0; j<BLOCK_HEIGHT; j++) {
  97.         pos2.y = j * GHOST_SIZE + pos->y;
  98.         for (k=0; k<BLOCK_WIDTH; k++) {
  99.             if ((maze[k][j] != POWER) || powerDotShown) {    // if power dot
  100.                 // blinked off, we don't render it.
  101.                 NXSetRect(&check, k * GHOST_SIZE, j * GHOST_SIZE,
  102.                     GHOST_SIZE, GHOST_SIZE);
  103.                 if (NXIntersectsRect(&check, rect)) { // only draw maze bits
  104.                     // in the rects that intersect the rect passed to us
  105.                     NXSetRect(&from,
  106.                         (maze[k][j] % PER_ROW) * GHOST_SIZE,
  107.                         (maze[k][j] / PER_ROW) * GHOST_SIZE,
  108.                         GHOST_SIZE, GHOST_SIZE);
  109.                     pos2.x = k * GHOST_SIZE + pos->x;
  110.                     [mazeParts composite:NX_SOVER
  111.                         fromRect:&from toPoint:&pos2];
  112.     }    }    }    }
  113.     return self;
  114.  
  115. }
  116.  
  117.  
  118. - makeMaze:(int)num
  119. {    // build a maze from the template; fill it with dots, set up new player and
  120.     // ghost positions, etc.
  121.     int j, k;
  122.     int ghost = 0;
  123.     int pdot = 0;
  124.     
  125.     dots = 0;
  126.     if ((num >= 0) && (num < MAZES)) { // make sure in range
  127.         mazeNum = num;
  128.         player[0] = -32; player[1] = -32; // sum is neg if no player spot found
  129.         // set up player/ghost/power dot position, etc. for maze.
  130.         for (j=0; j<BLOCK_HEIGHT; j++) {
  131.             for (k=0; k<BLOCK_WIDTH; k++) {
  132.                 maze[k][j] = mazes[num][k][j];
  133.                 switch (maze[k][j]) {
  134.                     case GHDOOR  : {    door[0] = k;    // door for ghosts
  135.                         door[1] = j; break; }
  136.                     case PLAYER  : { player[0] = k;        // Player
  137.                         player[1] = j;
  138.                         maze[k][j] = EMPTY; break; }
  139.                     case GHOST : { ghosts[ghost * 2] = k;    // Ghost
  140.                         ghosts[ghost * 2 + 1] = j;
  141.                         maze[k][j] = EMPTY;
  142.                         if (++ghost > MAX_GHOSTS) { fprintf(stderr,
  143.                             "Maze %d has too many ghosts.\n", num); }
  144.                         break; }
  145.                     case POWER : { power[pdot * 2] = k;    // Power Dot
  146.                         power[pdot * 2 + 1] = j; dots++;
  147.                         if (++pdot > MAX_POWER_DOTS) { fprintf(stderr,
  148.                             "Maze %d has too many power dots.\n", num); }
  149.                         break; }
  150.                     case DOT : { dots++;                    // Normal Dot
  151.                         break; }
  152.                     default : { break; }                // do nothing
  153.                 }
  154.             }
  155.         }
  156.         if (!ghost) { fprintf(stderr, "Maze %d has no ghosts.\n", num); }
  157.         if (!pdot) { fprintf(stderr, "Maze %d has no power dots.\n", num); }
  158.         if (player[0]+player[1] < 0) {
  159.             fprintf(stderr, "Maze %d has no player.\n", num); }
  160.     }
  161.     return self;
  162. }
  163.  
  164.  
  165. - playerPosition:(int *)x :(int *)y    // return x, y of player/fruit
  166. {
  167.     *x = player[0] * GHOST_SIZE; *y = player[1] * GHOST_SIZE;
  168.     return self;
  169. }
  170.  
  171.  
  172. - doorPosition:(int *)x :(int *)y    // return x, y of door to ghost chamber
  173. {
  174.     *x = door[0] * GHOST_SIZE; *y = door[1] * GHOST_SIZE;
  175.     return self;
  176. }
  177.  
  178.  
  179. - (const int *)powerDot            // return pointer to power array
  180. {
  181.     return power;
  182. }
  183.  
  184.  
  185. - (const int *)ghosts                // return pointer to ghosts array
  186. {
  187.     return ghosts;
  188. }
  189.  
  190.  
  191. - (BOOL)powerDotAt:(int)x :(int)y    // return YES if power dot in block
  192. {
  193.     // only have to be 1/2 way into block to eat dot:
  194.     int basex = x / GHOST_SIZE + ((x % GHOST_SIZE) > (GHOST_SIZE / 2));
  195.     int basey = y / GHOST_SIZE + ((y % GHOST_SIZE) > (GHOST_SIZE / 2));
  196.     
  197.     if (maze[basex][basey] == POWER) { // munch power dot
  198.         [[NXApp delegate] addToScore:POWERDOTPOINTS];
  199.         maze[basex][basey] = EMPTY;
  200.         dots--;
  201.         dotx = basex; doty = basey;    // save them away
  202.         return YES;
  203.     }
  204.     return NO;
  205. }
  206.  
  207. - (BOOL)eatDotAt:(int)x :(int)y        // return YES if OK, NO if no dot was there
  208. {
  209.     int basex = x / GHOST_SIZE;
  210.     int basey = y / GHOST_SIZE;
  211.     int dx = x % GHOST_SIZE;
  212.     int dy = y % GHOST_SIZE;
  213.     
  214.     if (!dx) { // in a vertical column or corner/junction
  215.         if (dy > GHOST_SIZE / 2) basey++;
  216.     } else { // on a horiz. row
  217.         if (dx > GHOST_SIZE / 2) basex++;
  218.     }
  219.     
  220.     if (maze[basex][basey] == DOT) { // munch dot
  221.         [[NXApp delegate] addToScore:DOTPOINTS];
  222.         maze[basex][basey] = EMPTY;
  223.         dots--;
  224.         dotx = basex; doty = basey;    // save them away
  225.         return YES;
  226.     }
  227.     return NO;
  228. }
  229.  
  230. - (int)dots                            // return the number of dots left in maze
  231. {
  232.     return dots;
  233. }
  234.  
  235. - lastDot:(int *)xx :(int *)yy
  236. {
  237.     *xx = dotx * GHOST_SIZE;
  238.     *yy = doty * GHOST_SIZE;
  239.     return self;
  240. }
  241.  
  242. - (BOOL)playerWall:(float)x :(float)y    // YES if player can't be in block
  243. {
  244.     int mazex = x / GHOST_SIZE;
  245.     int mazey = y / GHOST_SIZE;
  246.     
  247.     if ((maze[mazex][mazey] == EMPTY)    ||
  248.         (maze[mazex][mazey] == DOT)        ||
  249.         (maze[mazex][mazey] == POWER)) return NO;
  250.     return YES;
  251. }
  252.  
  253. - (BOOL)monsterWall:(float)x :(float)y    // YES if ghost can't be in block
  254. {
  255.     int mazex = x / GHOST_SIZE;
  256.     int mazey = y / GHOST_SIZE;
  257.     
  258.     if ((maze[mazex][mazey] == EMPTY)    ||
  259.         (maze[mazex][mazey] == DOT)        ||
  260.         (maze[mazex][mazey] == GHDOOR)    ||
  261.         (maze[mazex][mazey] == POWER)) return NO;
  262.     return YES;
  263. }
  264.  
  265. - blinkPowerDot                    // toggle ON/OFF state of power dots
  266. {
  267.     powerDotShown = !powerDotShown;
  268.     return self;
  269. }
  270.  
  271. - visible:(BOOL)flag                // used to tell us if the maze is visible
  272. {
  273.     visibleMaze = flag;
  274.     return self;
  275. }
  276.  
  277. - (BOOL)isVisible;                    // used to tell others if maze is visible
  278. { return visibleMaze; }
  279.  
  280.  
  281. @end
  282.